import cloneDeep from 'lodash/cloneDeep';
import { fetchEventSource } from '@microsoft/fetch-event-source'
import type { FetchEventSourceOptions, FetchEventSourceReturn } from '../models/fetch-event-source'
import { ERRORTYPE } from '../config/const';

/**
 * 发送sse请求
 * @param options 请求配置
 * @returns 控制器 controller 请求状态 promise
 */
export function sendSSE(options: FetchEventSourceOptions): { controller: AbortController, request: Promise<void> } {
  // 控制器 用于后续中断请求
  const controller = new AbortController()
  // 合并请求头
  const headers = {
    'Content-Type': 'application/json',
  }
  Object.assign(headers, options.headers)

  // 请求参数处理
  let body = '{}';
  if (options.data) {
    // get请求则参数拼接到url上
    if (options.method === 'GET') {
      const params = new URLSearchParams(options.data)
      options.url += '?' + params.toString()
    }
    // post请求则参数放在body中
    else {
      body = JSON.stringify(options.data)
    }
  }

  // 封装成promise 用于加载状态 及回答内容显隐控制
  const request = new Promise<any>((resolve, reject) => {
    fetchEventSource(
      options.url,
      {
        method: options.method || 'POST',
        headers,
        body,
        signal: controller.signal,
        openWhenHidden: true,
        onclose() {
          options.onclose && options.onclose()
          resolve(0)
        },
        onerror(err) {
          options.onerror && options.onerror(err)
          resolve(-1)
        },
        onmessage(ev) {
          try {
            const formatData: FetchEventSourceReturn = { ...cloneDeep(ev), data: JSON.parse(ev.data) }
            options.onmessage && options.onmessage(formatData)
          } catch (error) {
            window.f10log(ERRORTYPE.AJAX, `sse请求返回数据解析失败：${error}`, error)
            console.error('JSON.parse error', error)
          }
        },
        async onopen(response) {
          options.onopen && options.onopen(response)
        }
      }
    )
  })

  return { controller, request };
}